package com.bh.shipment.service.impl;

import com.bh.common.enums.OrderStatus;
import com.bh.common.enums.ShipmentStatus;
import com.bh.common.exception.ServiceException;
import com.bh.common.utils.DateUtils;
import com.bh.common.utils.SecurityUtils;
import com.bh.common.utils.bean.BeanUtils;
import com.bh.extend.domain.JcOrderBarcode;
import com.bh.extend.mapper.JcOrderBarcodeMapper;
import com.bh.extend.service.IJcOrderBarcodeService;
import com.bh.kysys.domain.JcSysOrganization;
import com.bh.kysys.service.IJcSysOrganizationService;
import com.bh.ledger.domain.JcLedgerDetail;
import com.bh.ledger.domain.JcVerificationZb;
import com.bh.ledger.service.IJcLedgerDetailService;
import com.bh.ledger.service.IJcVerificationZbService;
import com.bh.order.domain.*;
import com.bh.order.mapper.JcLedMapper;
import com.bh.order.mapper.JcLedProductMapper;
import com.bh.order.mapper.JcOrderMapper;
import com.bh.order.service.IJcLedReceivingpartyService;
import com.bh.order.service.IJcLedShipmentService;
import com.bh.order.service.IJcOrderTrackService;
import com.bh.shipment.domain.JcShipment;
import com.bh.shipment.mapper.JcShipmentMapper;
import com.bh.shipment.service.IJcShipmentCarryService;
import com.bh.shipment.service.IJcShipmentService;
import com.bh.shipment.service.IJcShipmentTrackService;
import com.bh.shipment.vo.JcAddShipmentVo;
import com.bh.vehicle.domain.JcCarrier;
import com.bh.vehicle.service.IJcCarrierService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class JcShipmentCarryServiceImpl implements IJcShipmentCarryService {
    @Autowired
    private JcShipmentMapper jcShipmentMapper;
    @Autowired
    private IJcOrderTrackService jcOrderTrackService;
    @Autowired
    private IJcShipmentService jcShipmentService;
    @Autowired
    private JcOrderBarcodeMapper jcOrderBarcodeMapper;
    @Autowired
    private JcLedMapper jcLedMapper;
    @Autowired
    private JcOrderMapper jcOrderMapper;
    @Autowired
    private IJcLedReceivingpartyService jcLedReceivingpartyService;
    @Autowired
    private JcLedProductMapper jcLedProductMapper;
    @Autowired
    private IJcOrderBarcodeService jcOrderBarcodeService;
    @Autowired
    private IJcLedShipmentService ledShipmentService;
    @Autowired
    private IJcShipmentTrackService jcShipmentTrackService;
    @Autowired
    private IJcVerificationZbService jcVerificationZbService;
    @Autowired
    private IJcLedgerDetailService jcLedgerDetailService;
    @Autowired
    private IJcCarrierService carrierService;
    @Autowired
    private IJcSysOrganizationService sysOrganizationService;

    @Override
    public int addLed(JcAddShipmentVo shipmentVo) {
        JcShipment shipment = jcShipmentMapper.selectById(shipmentVo.getJcShipmentId());
        // 先获取已经装载的 分段订单（LED）
        Map<String, Map<String, Long>> ledOrders = jcOrderBarcodeMapper.selectLedOrderIdsByShipmentId(shipmentVo.getJcShipmentId());
        //拆单规则
        List<Long> ledIds;
        if (shipmentVo.getLedIds() != null && shipmentVo.getLedIds().length > 0) {
            ledIds = Arrays.asList(shipmentVo.getLedIds());
        } else {
            List<JcOrderBarcode> shipmentCodes = jcOrderBarcodeMapper.selectJcOrderBarcodeListByShipmentId(shipmentVo.getJcShipmentId());
            if (shipmentCodes == null || shipmentCodes.isEmpty()) {
                throw new ServiceException("请先装载货物！");
            }
            ledIds = shipmentCodes.stream().map(JcOrderBarcode::getLedOrderId).distinct().collect(Collectors.toList());
        }

        List<JcLed> leds = jcLedMapper.selectBatchIds(ledIds);
        //数据验证
        for (JcLed led : leds) {
            // 优先进行检测
            if (led.getStatus() == OrderStatus.STOWAGE.getValue()) {
                throw new ServiceException("分段订单号:" + led.getCode() + "已经被其他运单配载,请重新选择");
            }
            JcOrder order = jcOrderMapper.selectById(led.getJcOrderId());
            List<JcOrderBarcode> barcodes = jcOrderBarcodeMapper.selectJcOrderBarcodeListByLedId(led.getId());
            // 重新设置为 map
            Map<Long, List<JcOrderBarcode>> productMap = barcodes.stream().collect(Collectors.groupingBy(JcOrderBarcode::getLedProductId));
            List<JcLedProduct> ledProducts = jcLedProductMapper.selectJcLedProductListByLedId(led.getId());
            // map 标识查询到已经装载的数量
            Integer loadNum = ledOrders.get(led.getId()).get("scan_number").intValue();
            // 订单数量大于装车数量则进行拆分
            if (led.getNumber() > loadNum && shipmentVo.getFinishType() == 1) {
                /**
                 * 根据数量判断是否拆分，将原有的单条数据的拆分逻辑进行修改，
                 * 只需修改数量，当提交的数量小于总数并且确认拆分的情况下则直接进行拆分，
                 * 会自动生成一条新的分段订单并将产品的代码表中的产品分配到新的订单中，并将 jc_led_product 中的内容自动 进行拆分
                 */
                //处理当前 led
                Integer oldNum = led.getNumber();
                BigDecimal oldValue = led.getValue();
                BigDecimal oldVolume = led.getVolume();
                BigDecimal oldWeight = led.getWeight();
                BigDecimal oldJzWeight = led.getJzWeight();
                BigDecimal percent = new BigDecimal(loadNum).divide(new BigDecimal(oldNum), 2, RoundingMode.HALF_UP);
                //开始减去拆分数据
                led.setNumber(loadNum);
                led.setWeight(oldWeight.multiply(percent));
                led.setVolume(oldVolume.multiply(percent));
                led.setValue(oldValue.multiply(percent));
                if (oldJzWeight != null) {
                    led.setJzWeight(oldJzWeight.multiply(percent));
                }

                //新增克隆对象
                JcLed cloneObj = BeanUtils.cloneObject(led, JcLed.class);
                cloneObj.setId(null);//处理克隆对象
                cloneObj.setNumber(oldNum - led.getNumber());
                cloneObj.setWeight(oldWeight.subtract(led.getWeight()));
                cloneObj.setValue(oldValue.subtract(led.getValue()));
                cloneObj.setVolume(oldVolume.subtract(led.getVolume()));
                if (oldJzWeight != null) {
                    cloneObj.setJzWeight(oldJzWeight.subtract(led.getVolume()));
                }
                //处理分段运单单号
                String code = led.getCode();
                long count = jcLedMapper.selectJcLedListByJcOrderId(order.getId()) + 1;
                String newCode = code.substring(0, code.indexOf("-")) + "-" + count;
                cloneObj.setCode(newCode);
                cloneObj.setBackNumber(0);
                cloneObj.setAgent(BigDecimal.ZERO);
                cloneObj.setCreateName(SecurityUtils.getUsername());
                cloneObj.setCreateTime(DateUtils.getNowDate());
                jcLedMapper.insert(cloneObj);

                // 收发地址一致，因此直接进行复制新增
                List<JcLedReceivingParty> ledReceivingParties = jcLedReceivingpartyService.selectJcLedReceivingPartyListByLedId(led.getId());
                for (JcLedReceivingParty newLedReceivingParty : ledReceivingParties) {
                    newLedReceivingParty.setJcLedId(cloneObj.getId());
                    newLedReceivingParty.setId(null);
                    jcLedReceivingpartyService.insertJcLedReceivingparty(newLedReceivingParty);
                }

                //处理货品明细,将老数据的数量等设置为已装载的数量，未装载的全部设置为  cloneObj的ledId
                for (JcLedProduct product : ledProducts) {
                    // 将装转的数量进行修改, 重新设置为 map
                    Map<String, List<JcOrderBarcode>> packStatusMap = productMap.get(product.getId()).stream().collect(Collectors.groupingBy(JcOrderBarcode::getPackStatus));
                    // 将已装载的数量更新
                    List<JcOrderBarcode> loadList = packStatusMap.get("Y");
                    Integer oldProductNum = product.getNumber();
                    int loadProductNum = loadList.size();
                    // 只有原数量大于装载数量的情况下才需要拆分
                    if (oldProductNum != null && oldProductNum > 0 && oldProductNum > loadProductNum) {
                        BigDecimal oldProductValue = led.getValue();
                        BigDecimal oldProductVolume = led.getVolume();
                        BigDecimal oldProductWeight = led.getWeight();
                        BigDecimal oldProductJzWeight = led.getJzWeight();
                        BigDecimal productPercent = new BigDecimal(loadProductNum).divide(new BigDecimal(oldProductNum), 2, RoundingMode.HALF_UP);

                        //处理原数据
                        product.setNumber(loadProductNum);
                        product.setWeight(oldProductWeight.multiply(productPercent));
                        product.setValue(oldProductValue.multiply(productPercent));
                        product.setVolume(oldProductVolume.multiply(productPercent));
                        if (oldProductJzWeight != null) {
                            product.setJzWeight(oldProductJzWeight.multiply(productPercent));
                        }
                        product.setModifyTime(DateUtils.getNowDate());
                        product.setModifyName(SecurityUtils.getUsername());
                        // 更新原数据
                        jcLedProductMapper.updateById(product);
                        // 将未装载的数量新增, 更新未装载的code
                        List<JcOrderBarcode> notLoadList = packStatusMap.get("N");
                        if (notLoadList != null && notLoadList.size() > 0) {
                            JcLedProduct cloneProduct = BeanUtils.cloneObject(product, JcLedProduct.class);
                            cloneProduct.setId(null);
                            cloneProduct.setNumber(notLoadList.size());
                            cloneProduct.setVolume(oldProductVolume.subtract(product.getVolume()));
                            cloneProduct.setValue(oldProductValue.subtract(product.getValue()));
                            cloneProduct.setWeight(oldProductWeight.subtract(product.getWeight()));
                            if (oldProductJzWeight != null) {
                                cloneProduct.setJzWeight(oldProductJzWeight.subtract(product.getJzWeight()));
                            }
                            cloneProduct.setCreateTime(DateUtils.getNowDate());
                            cloneProduct.setCreateName(SecurityUtils.getUsername());
                            cloneProduct.setModifyTime(DateUtils.getNowDate());
                            cloneProduct.setModifyName(SecurityUtils.getUsername());
                            cloneProduct.setJcLedId(cloneObj.getId());
                            jcLedProductMapper.insert(cloneProduct);

                            for (JcOrderBarcode barcode : notLoadList) {
                                barcode.setLedOrderId(cloneObj.getId());
                                barcode.setLedProductId(cloneProduct.getId());
                            }
                            jcOrderBarcodeService.updateBatchById(notLoadList);
                        }
                    }
                }
                order.setIsTake(1);
                order.setStatus(OrderStatus.STOWAGE_PART.getValue()); //修改订单状态
            } else {
                order.setStatus(OrderStatus.STOWAGE.getValue()); //修改订单状态
            }
            //插入关联表
            JcLedShipment jcLedShipment = new JcLedShipment();
            jcLedShipment.setJcShipmentId(shipmentVo.getJcShipmentId());
            jcLedShipment.setJcLedId(led.getId());
            ledShipmentService.insertJcLedShipment(jcLedShipment);
            // 更新原始led
            led.setActNumber(loadNum);
            led.setStatus(OrderStatus.STOWAGE.getValue()); //修改分段订单状态
            led.setJcShipmentId(shipmentVo.getJcShipmentId());
            jcLedMapper.updateById(led);
            // 更新order
            jcOrderMapper.updateById(order);
            updateLedgerDetail(order.getId(), shipmentVo.getJcShipmentId());
            shipment.getLeds().add(led);
            jcShipmentTrackService.addTrack(shipmentVo.getJcShipmentId(), "运单已经配载分段订单 分段订单号:" + led.getCode() + "   配载货品数量:" + led.getNumber() + "  重量:" + led.getWeight() + "  体积:" + led.getVolume() + "  货值:" + led.getValue());
        }
        costCustomerNum(shipment);
        //运单锁定确认
        return confirmShipment(shipmentVo.getJcShipmentId());
    }

    private void updateLedgerDetail(Long orderId, Long jcShipmentId) {
        // 查询出对应台账明细
        List<JcLedgerDetail> ledgerDetails = jcLedgerDetailService.selectNoUseJcLedgerDetailListByField1(String.valueOf(orderId));
        if (ledgerDetails != null && ledgerDetails.size() > 0) {
            for (JcLedgerDetail ledgerDetail : ledgerDetails) {
                ledgerDetail.setJcShipmentId(jcShipmentId);
            }
            jcLedgerDetailService.updateBatchById(ledgerDetails);
        }
    }

    /**
     * @param shipment
     * @return
     */
    private int costCustomerNum(JcShipment shipment) {
        StringBuilder customerNum = new StringBuilder();
        StringBuilder orderCode = new StringBuilder();
        //默认是存在的
        List<JcLed> leds = shipment.getLeds();
        for (JcLed led : leds) {
            customerNum.append(led.getRelateBill1()).append("/");
            orderCode.append(led.getCode()).append("/");
        }
        if (customerNum.length() != 0) {
            customerNum.deleteCharAt(customerNum.lastIndexOf("/"));
        }
        if (orderCode.length() != 0) {
            orderCode.deleteCharAt(orderCode.lastIndexOf("/"));
        }
        shipment.setRelateBill1(customerNum.toString());
        shipment.setOrderCode(orderCode.toString());
        return jcShipmentMapper.updateById(shipment);
    }


    public int confirmShipment(Long id) {
        JcShipment shipment = jcShipmentService.selectJcShipmentById(id);
        if (shipment.getStatus() != 1) {
            throw new ServiceException("只能确认保存状态下的运单");
        }
        JcSysOrganization organization = sysOrganizationService.getById(shipment.getJcOrganizationId());
        //判定超期
        if (shipment.getJcCarrierId() != null && shipment.getCarrierType() == 1) {
            JcCarrier jcCarrier = carrierService.getById(shipment.getJcCarrierId());
            Date startTime = jcCarrier.getStartTime();
            Date endTime = jcCarrier.getEndTime();
            Date df = new Date();
            boolean b = DateUtils.belongCalendar(df, startTime, endTime);

            if (organization.getIsOverdueCarrier() == 0) {
                if (!b) {
                    throw new ServiceException("承运商超期不能确认");
                } else {
                    shipment.setCarriageIsExceed(1);
                }
            }
        }
        if (shipment.getLeds() == null || shipment.getLeds().size() == 0) {
            throw new ServiceException("运单未配载不能确认");
        }
        shipment.setStatus(ShipmentStatus.CONFIGRM.getValue());//修改运单状态
        //处理装卸信息;
        List<JcLed> leds = shipment.getLeds();
        Integer number = 0;
        BigDecimal volume = BigDecimal.ZERO;
        BigDecimal weight = BigDecimal.ZERO;
        BigDecimal jz = BigDecimal.ZERO;
        for (JcLed led : leds) {
            //处理在途跟踪
            //int aaa= shipment.getRefuse();
            if (shipment.getRefuse() == 0) {
                //如果被拒收过
                jcOrderTrackService.addTrack(led.getJcOrderId(), "分段订单:" + led.getCode() + "   已被配载，等待发运…… 操作人:" + SecurityUtils.getUsername());
            }
            number += led.getNumber();
            volume = volume.add(led.getVolume());
            weight = weight.add(led.getWeight());
            jz = jz.add(led.getJzWeight());
        }
        shipment.setNumber(number);
        shipment.setVolume(volume);
        shipment.setWeight(weight);
        shipment.setJzWeight(jz);
        int num = jcShipmentMapper.updateById(shipment);
        List<JcLedgerDetail> ledgerDetails = jcLedgerDetailService.selectJcLedgerDetailListByShipmentId(id);
        BigDecimal amount = BigDecimal.ZERO;
        BigDecimal input = BigDecimal.ZERO;
        for (JcLedgerDetail ledgerDetail : ledgerDetails) {
            amount = amount.add(ledgerDetail.getAmount());
            input = input.add(ledgerDetail.getInput());
        }
        if (amount.compareTo(BigDecimal.ZERO) > 0) {
            JcVerificationZb verificationZb = new JcVerificationZb();
            verificationZb.setJcShipmentId(id);
            verificationZb.setJcOrganizationId(shipment.getJcOrganizationId());
            verificationZb.setHxStatus(0);
            verificationZb.setWhxMoney(amount);
            verificationZb.setZinput(input);
            verificationZb.setZmoney(amount);
            verificationZb.setTzSource(0L);
            verificationZb.setType(1);
            verificationZb.setHxMoney(BigDecimal.ZERO);
            jcVerificationZbService.insertJcVerificationZb(verificationZb);
        }

        //处理运单追踪
        if (shipment.getRefuse() == 0) {
            //如果被拒收过
            jcShipmentTrackService.addTrack(id, "运单已经确认 运单货品数量:" + shipment.getNumber() + "  重量:" + shipment.getWeight() + "  体积:" + shipment.getVolume() + "  货值:" + (shipment.getValue() == null ? BigDecimal.ZERO : shipment.getValue()));
        }
        return num;
    }
}
